package com.example.myblog.controller;

import cn.hutool.core.lang.Range;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.myblog.common.lang.Result;
import com.example.myblog.config.RabbitConfig;
import com.example.myblog.entity.*;
import com.example.myblog.search.mq.PostMqIndexMessage;
import com.example.myblog.utils.UploadUtil;
import com.example.myblog.utils.ValidationUtil;
import com.example.myblog.vo.CommentVo;
import com.example.myblog.vo.PostVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;


@Controller
public class PostController extends BaseController{

    @Autowired
    UploadUtil uploadUtil;

    /**
     * 按分类展示帖子
     * @param id
     * @return
     */
    @GetMapping("/category/{id:\\d}")
    public String category(@PathVariable("id") Long id){

        int pn = ServletRequestUtils.getIntParameter(request, "pn", 1);
        request.setAttribute("pn",pn);
        request.setAttribute("currentCategoryId",id);
        return "post/category";
    }

    /**
     * 查看帖子详情
     * @param id:帖子ID
     * @return
     */
//    @GetMapping("/post/{id:\\d}"):这样似乎匹配不到数值很大的ID
    @GetMapping("/post/{id}")
    public String detail(@PathVariable("id") Long id){

        //从数据库中查询
        //涉及到多表查询，因为要展示发帖人的名字、头像
        PostVo vo = postService.selectOnePost(new QueryWrapper<MPost>().eq("p.id",id));
        Assert.notNull(vo,"文章已被删除");

        //从redis里获取文章阅读数，因为文章阅读数的累计可以很多，每次都写入数据库太耗时和浪费资源
        postService.putViewCount(vo);

        //1分页  2文章ID  3用户ID  4排序
        //按文章发表时间排序，查询数据库
        IPage<CommentVo> results = commentService.paging(getPage(),vo.getId(),null,"created");

        request.setAttribute("post",vo);
        request.setAttribute("currentCategoryId",id);
        request.setAttribute("pageData",results);
        System.out.println(results.getRecords());
        return "post/detail";
    }

    /**
     * 判断用户是否收藏了文章
     * @param pid
     * @return
     */
    @ResponseBody
    @PostMapping("/collection/find/")
    public Result collectionFind(Long pid) {
        int count = collectionService.count(new QueryWrapper<MUserCollection>()
                .eq("user_id", getProfileId())
                .eq("post_id", pid)
        );
        return Result.success(MapUtil.of("collection", count > 0 ));
    }


    /**
     * 添加收藏
     * @param pid：帖子ID
     * @return
     */
    @ResponseBody
    @PostMapping("/collection/add/")
    public Result collectionAdd(Long pid) {
        MPost post = postService.getById(pid);

        Assert.isTrue(post != null, "改帖子已被删除");
        int count = collectionService.count(new QueryWrapper<MUserCollection>()
                .eq("user_id", getProfileId())
                .eq("post_id", pid)
        );
        if(count > 0) {
            return Result.fail("你已经收藏");
        }

        MUserCollection collection = new MUserCollection();
        collection.setUserId(getProfileId());
        collection.setPostId(pid);
        collection.setCreated(new Date());
        collection.setModified(new Date());
        collection.setPostUserId(post.getUserId());
        //往数据库里插入记录
        collectionService.save(collection);
        return Result.success();
    }

    /**
     * 取消收藏
     * @param pid：帖子ID
     * @return
     */
    @ResponseBody
    @PostMapping("/collection/remove/")
    public Result collectionRemove(Long pid) {
        MPost post = postService.getById(pid);
        Assert.isTrue(post != null, "改帖子已被删除");
        collectionService.remove(new QueryWrapper<MUserCollection>()
                .eq("user_id", getProfileId())
                .eq("post_id", pid));

        return Result.success();
    }

    /**
     * 编辑文章
     * @return
     */
    @GetMapping("/post/edit")
    public String edit(){
        String id = request.getParameter("id");
        if(!StringUtils.isEmpty(id)) {
            MPost post = postService.getById(id);
            Assert.isTrue(post != null, "该帖子已被删除");
            Assert.isTrue(post.getUserId().longValue() == getProfileId().longValue(), "没权限操作此文章");
            request.setAttribute("post", post);
        }
        request.setAttribute("categories", categoryService.list());
        return "/post/edit";
    }


    @ResponseBody
    @PostMapping("/post/submit")
    public Result submit(MPost post) {
        //驗證內容完整
        ValidationUtil.ValidResult validResult = ValidationUtil.validateBean(post);
        if(validResult.hasErrors()) {
            return Result.fail(validResult.getErrors());
        }

        //发表帖子
        if(post.getId() == null) {
            post.setUserId(getProfileId());
            post.setModified(new Date());
            post.setCreated(new Date());
            post.setCommentCount(0);
            post.setEditMode(null);
            post.setLevel(0);
            post.setRecommend(false);
            post.setViewCount(0);
            post.setVoteDown(0);
            post.setVoteUp(0);
            postService.save(post);

        } else {//编辑帖子
            MPost tempPost = postService.getById(post.getId());
            //表达式为false,就会抛异常
            //验证当前用户是否该贴主人
            Assert.isTrue(tempPost.getUserId().longValue() == getProfileId().longValue(), "无权限编辑此文章！");
            tempPost.setTitle(post.getTitle());
            tempPost.setContent(post.getContent());
            tempPost.setCategoryId(post.getCategoryId());
            postService.updateById(tempPost);
        }

        // 通知消息给mq，告知更新或添加，功能是同步elasticsearch库信息
        amqpTemplate.convertAndSend(RabbitConfig.es_exchage, RabbitConfig.es_bind_key,
                new PostMqIndexMessage(post.getId(), PostMqIndexMessage.CREATE_OR_UPDATE));

        //跳转到刚发表的帖子详情页
        return Result.success().action("/post/" + post.getId());
    }

    @ResponseBody
    @Transactional
    @PostMapping("/post/delete")
    public Result delete(Long id) {
        MPost post = postService.getById(id);

        Assert.notNull(post, "该帖子已被删除");
        Assert.isTrue(post.getUserId().longValue() == getProfileId().longValue(), "无权限删除此文章！");

        postService.removeById(id);

        // 删除相关消息、收藏等
        messageService.removeByMap(MapUtil.of("post_id", id));
        collectionService.removeByMap(MapUtil.of("post_id", id));

        //发送删除通知(rabbitMq队列)
        amqpTemplate.convertAndSend(RabbitConfig.es_exchage, RabbitConfig.es_bind_key,
                new PostMqIndexMessage(post.getId(), PostMqIndexMessage.REMOVE));

        return Result.success().action("/user/index");
    }


    /**
     *
     * @param pid:帖子id
     * @param content：评论内容
     * @return
     */
    @ResponseBody
    @Transactional
    @PostMapping("/post/reply/")
    public Result reply(Long pid, String content) {
        Assert.notNull(pid, "找不到对应的文章");
        Assert.hasLength(content, "评论内容不能为空");

        //查找文章
        MPost post = postService.getById(pid);
        Assert.isTrue(post != null, "该文章已被删除");

        //初始化数据，评论日期、点赞数等等
        MComment comment = new MComment();
        comment.setPostId(pid);
        comment.setContent(content);
        comment.setUserId(getProfileId());
        comment.setCreated(new Date());
        comment.setModified(new Date());
        comment.setLevel(0);
        comment.setVoteDown(0);
        comment.setVoteUp(0);
        commentService.save(comment);

        // 评论数量加一：这样写线程不安全
        post.setCommentCount(post.getCommentCount() + 1);
        //更新，评论数加一
        postService.updateById(post);

        // 本周热议数量加一
        postService.incrCommentCountAndUnionForWeekRank(post.getId(), true);

        // 通知作者，有人评论了你的文章
        // 作者自己评论自己文章，不需要通知
        if(comment.getUserId().longValue() != post.getUserId().longValue()) {
            MUserMessage message = new MUserMessage();
            message.setPostId(pid);
            message.setCommentId(comment.getId());
            message.setFromUserId(getProfileId());
            message.setToUserId(post.getUserId());
            message.setType(1);
            message.setContent(content);
            message.setCreated(new Date());
            message.setStatus(0);
            messageService.save(message);

            // 即时通知作者（websocket），发送消息通知
            wsService.sendMessCountToUser(message.getToUserId());
        }

        //前端自动加上@username
        // 通知被@的人，有人回复了你的文章
        if(content.startsWith("@")) {
            String username = content.substring(1, content.indexOf(" "));
            System.out.println(username);
            //查找出被回复的用户
            MUser user = userService.getOne(new QueryWrapper<MUser>().eq("username", username));
            if(user != null) {
                MUserMessage message = new MUserMessage();
                message.setPostId(pid);
                message.setCommentId(comment.getId());
                message.setFromUserId(getProfileId());
                message.setToUserId(user.getId());
                message.setType(2);
                message.setContent(content);
                message.setCreated(new Date());
                message.setStatus(0);
                //插入消息表
                messageService.save(message);

                // 即时通知被@的用户，发送消息通知
                wsService.sendMessCountToUser(message.getToUserId());
            }
        }
        return Result.success().url("/post/" + post.getId());
    }


    /**
     * 删除评论
     * @param cid
     * @return
     */
    @ResponseBody
    @Transactional
    @PostMapping("/post/jieda-delete/")
    public Result reply(String cid) {

        System.out.println(cid);
        String replace = cid.replace(",", "");
        long id = Long.parseLong(replace);
        Assert.notNull(id, "评论id不能为空！");

        MComment comment = commentService.getById(id);

        Assert.notNull(comment, "找不到对应评论！");

        Long userId = postService.getOne(new QueryWrapper<MPost>()
                .eq("id", comment.getPostId())).getUserId();

        if (getProfileId().longValue() == userId || comment.getUserId().longValue() == getProfileId().longValue()){
            commentService.removeById(id);

            // 评论数量减一
            MPost post = postService.getById(comment.getPostId());
            post.setCommentCount(post.getCommentCount() - 1);
            postService.saveOrUpdate(post);
            //评论数量减一
            postService.incrCommentCountAndUnionForWeekRank(comment.getPostId(), false);
            return Result.success(null);
        }else  {
            return Result.fail("不是你发表的评论！");
        }


    }


    //上传图片，写入硬盘
    @ResponseBody
    @PostMapping("/post/upload")
    public Result uploadAvatar(@RequestParam(value = "file") MultipartFile file) throws IOException {
        return uploadUtil.upload(UploadUtil.type_post, file);
    }
}
